package com.example.aitoedu.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.example.aitoedu.config.WenXinConfig;
import com.example.aitoedu.constant.MessageConstant;
import com.example.aitoedu.controller.student.AIController;
import com.example.aitoedu.dto.AIReceiveDTO;
import com.example.aitoedu.entity.Conversation;
import com.example.aitoedu.entity.Title;
import com.example.aitoedu.exception.NetworkErrorException;
import com.example.aitoedu.mapper.ConversationMapper;
import com.example.aitoedu.mapper.TitleMapper;
import com.example.aitoedu.service.ConversationService;
import com.example.aitoedu.vo.AIStatisticsVO;
import com.example.aitoedu.vo.OnlyConversationVO;
import com.example.aitoedu.vo.OnlyTitleVO;
import com.example.aitoedu.vo.TitleVO;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author 曹正豪
* @description 针对表【conversation(对话信息)】的数据库操作Service实现
* @createDate 2024-08-28 19:43:11
*/
@Service
@Slf4j
public class ConversationServiceImpl extends ServiceImpl<ConversationMapper, Conversation>
    implements ConversationService{

    @Autowired
    private ConversationMapper conversationMapper;

    @Autowired
    private TitleMapper titleMapper;

    @Autowired
    private AIController aiController;

    @Autowired
    private WenXinConfig wenXinConfig;

    @Override
    public List<TitleVO> allConversation() {
        Long sid = Long.valueOf((String) StpUtil.getLoginId());
        List<TitleVO> lists = conversationMapper.allConversation(sid);
        List<TitleVO> collect = lists.stream()
                .map(list -> {
                    if(list.getConversaiotnVOList().size()>0){
                        list.setTotal(list.getConversaiotnVOList().size());
                        list.setNewTime(list.getConversaiotnVOList().get(0).getCreateTime());
                    }else {
                        list.setTotal(0);
                        list.setNewTime(titleMapper.getCreateTimeById(list.getTitleId()));
                    }
                    return list;
                })
                .sorted(Comparator.comparing(TitleVO::getNewTime).reversed())
                .collect(Collectors.toList());
        log.info("排序和赋值后的全部对话：{}",collect);
        return collect;
    }

    @Override
    public SaResult save(Long titleId) {
        Title title = titleMapper.selectOne(new QueryWrapper<Title>().eq("id",titleId).eq("save",1));
        if(!ObjectUtils.isEmpty(title)) return SaResult.error(MessageConstant.SAVE_ALREADY);
        titleMapper.save(titleId);
        return SaResult.ok(MessageConstant.SAVE_SUCCESS);
    }

    @Override
    public OnlyTitleVO onlyConversation(Long titleId) {
        OnlyTitleVO onlyTitleVO = conversationMapper.onlyConversation(titleId);
        if(!ObjectUtils.isEmpty(onlyTitleVO)){
            onlyTitleVO.setOnlyConversationVOList(conversationMapper.getOnlyOne(titleId));
            if(onlyTitleVO.getOnlyConversationVOList()!=null)
                onlyTitleVO.setTotal(onlyTitleVO.getOnlyConversationVOList().size());
        }
        return onlyTitleVO;
    }

    @Override
    public String receive(AIReceiveDTO aiReceiveDTO) {
        Conversation conversation =  Conversation.builder()
                .content(aiReceiveDTO.getContent())
                .role(1)
                .createTime(LocalDateTime.now())
                .titleId(aiReceiveDTO.getTitleId())
                .build();
        String AIReplay = aiController.send(aiReceiveDTO);
        conversationMapper.insert(conversation);
        conversation.setContent(AIReplay);
        conversation.setRole(0);
        conversation.setCreateTime(LocalDateTime.now());
        conversation.setId(null);
        conversationMapper.insert(conversation);
        return AIReplay;
    }

    @Override
    public AIStatisticsVO statistics() {
        Long sid = Long.valueOf((String) StpUtil.getLoginId());
        LocalDateTime today = LocalDateTime.now();
        List<Title> lists = titleMapper.selectList(new QueryWrapper<Title>()
                .eq("sid",sid)
                .le("create_time",today)
                .ge("create_time",today.withHour(0).withMinute(0).withSecond(0))
                .ge("is_deleted",1)
        );
        Integer todaySession = lists.size();
        return AIStatisticsVO.builder()
                .todaySession(todaySession)
                .build();
    }

    @Override
    //流式请求
    public String send(AIReceiveDTO aiReceiveDTO){
        HashMap<String, String> r = new HashMap<>();
        OkHttpClient client = new OkHttpClient();
        List<Map<String,String>> messages = new ArrayList<>();
        OnlyTitleVO onlyTitleVO = this.onlyConversation(aiReceiveDTO.getTitleId());
        if (wenXinConfig.flushAccessToken() != null) {
            if(!ObjectUtils.isEmpty(onlyTitleVO) && onlyTitleVO.getOnlyConversationVOList() !=null){
                List<OnlyConversationVO> onlyConversationVOList = onlyTitleVO.getOnlyConversationVOList();
                HashMap<String, String> userTemp = new HashMap<>();
                userTemp.put("role","user");
                userTemp.put("content","你好");
                messages.add(userTemp);
              for(int i = onlyConversationVOList.size() - 1; i>=0; i--){
                    switch (onlyConversationVOList.get(i).getRole()){
                        case 0: HashMap<String, String> assistant = new HashMap<>();
                                assistant.put("role","assistant");
                                assistant.put("content",onlyConversationVOList.get(i).getContent());
                                messages.add(assistant);
                                break;
                        case 1: HashMap<String, String> user = new HashMap<>();
                                user.put("role","user");
                                user.put("content",onlyConversationVOList.get(i).getContent());
                                messages.add(user);
                                break;
                    }
                 }
            }
            HashMap<String, String> user = new HashMap<>();
            user.put("role","user");
            user.put("content",aiReceiveDTO.getContent());
            messages.add(user);
            log.info("要发送给ai的内容：{}",messages);
            log.info("内容长度：{}",messages.size());
            String requestJson = this.constructRequestJson(Integer.valueOf((String) StpUtil.getLoginId()),
                    0.95,0.8,1.0,true,messages);
            RequestBody body = RequestBody.create(MediaType.parse("application/json"), requestJson);
            Request request = new Request.Builder()
                    .url(wenXinConfig.ERNIE_Bot_4_0_URL + "?access_token=" + wenXinConfig.flushAccessToken())
                    .method("POST", body)
                    .addHeader("Content-Type", "application/json")
                    .build();
            StringBuilder answer = new StringBuilder();
            try {
                Response response = client.newCall(request).execute();
                log.info("reponse:{}",response);
                // 检查响应是否成功
                if (response.isSuccessful()) {
                    // 获取响应流
                    try (ResponseBody responseBody = response.body()) {
                        if (responseBody != null) {
                            InputStream inputStream = responseBody.byteStream();
                            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                            // 以流的方式处理响应内容
                            byte[] buffer = new byte[1024*1024*5];
                            int bytesRead;
                            while ((bytesRead = inputStream.read(buffer)) != -1) {
                                // 在控制台输出每个数据块
//                                System.out.write(buffer, 0, bytesRead);
                                //将结果汇总起来
                                answer.append(new String(buffer, 0, bytesRead));
                            }
                        }
                    }
                } else {
                    System.out.println("Unexpected code " + response);
                }

            } catch (IOException e) {
                log.error("流式请求出错");
                throw new NetworkErrorException(MessageConstant.NETWORK_ERROR);
            }
            String[] answerArray = answer.toString().split("data: ");
            for (int i=1;i<answerArray.length;++i) {
                  answerArray[i] = answerArray[i].substring(0,answerArray[i].length() - 2);
                r.put("content",r.get("content") + JSON.parseObject(answerArray[i]).get("result"));
            }
        }
        return r.get("content").replaceFirst("null","");
    }

    public String constructRequestJson(Integer userId,
                                       Double temperature,
                                       Double topP,
                                       Double penaltyScore,
                                       boolean stream,
                                       List<Map<String, String>> messages) {
        Map<String,Object> request = new HashMap<>();
        request.put("user_id",userId.toString());
        request.put("temperature",temperature);
        request.put("top_p",topP);
        request.put("penalty_score",penaltyScore);
        request.put("stream",stream);
        request.put("messages",messages);
        return JSON.toJSONString(request);
    }
}




